home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / Mesa-3.0 / SRC / PB.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-01  |  12.6 KB  |  410 lines

  1. /* $Id: pb.c,v 3.4 1998/04/01 02:58:52 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.0
  6.  * Copyright (C) 1995-1998  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: pb.c,v $
  26.  * Revision 3.4  1998/04/01 02:58:52  brianp
  27.  * applied Miklos Fazekas's 3-31-98 Macintosh changes
  28.  *
  29.  * Revision 3.3  1998/03/05 02:59:05  brianp
  30.  * [RGBA]COMP wasn't being used in a few places
  31.  *
  32.  * Revision 3.2  1998/02/20 04:50:44  brianp
  33.  * implemented GL_SGIS_multitexture
  34.  *
  35.  * Revision 3.1  1998/02/15 01:32:37  brianp
  36.  * fixed a comment
  37.  *
  38.  * Revision 3.0  1998/01/31 21:00:28  brianp
  39.  * initial rev
  40.  *
  41.  */
  42.  
  43.  
  44. /*
  45.  * Pixel buffer:
  46.  *
  47.  * As fragments are produced (by point, line, and bitmap drawing) they
  48.  * are accumlated in a buffer.  When the buffer is full or has to be
  49.  * flushed (glEnd), we apply all enabled rasterization functions to the
  50.  * pixels and write the results to the display buffer.  The goal is to
  51.  * maximize the number of pixels processed inside loops and to minimize
  52.  * the number of function calls.
  53.  */
  54.  
  55.  
  56.  
  57. #ifdef PC_HEADER
  58. #include "all.h"
  59. #else
  60. #include <stdlib.h>
  61. #include <string.h>
  62. #include "alpha.h"
  63. #include "alphabuf.h"
  64. #include "blend.h"
  65. #include "depth.h"
  66. #include "fog.h"
  67. #include "logic.h"
  68. #include "macros.h"
  69. #include "masking.h"
  70. #include "pb.h"
  71. #include "scissor.h"
  72. #include "stencil.h"
  73. #include "texture.h"
  74. #include "types.h"
  75. #endif
  76.  
  77.  
  78.  
  79. /*
  80.  * Allocate and initialize a new pixel buffer structure.
  81.  */
  82. struct pixel_buffer *gl_alloc_pb(void)
  83. {
  84.    struct pixel_buffer *pb;
  85.    pb = (struct pixel_buffer *) calloc(sizeof(struct pixel_buffer), 1);
  86.    if (pb) {
  87.       int i;
  88.       /* set non-zero fields */
  89.       pb->primitive = GL_BITMAP;
  90.       /* Set all lambda values to 0.0 since we don't do mipmapping for
  91.        * points or lines and want to use the level 0 texture image.
  92.        */
  93.       for (i=0; i<PB_SIZE; i++) {
  94.          pb->lambda[i] = 0.0;
  95.       }
  96.    }
  97.    return pb;
  98. }
  99.  
  100.  
  101.  
  102.  
  103. /*
  104.  * When the pixel buffer is full, or needs to be flushed, call this
  105.  * function.  All the pixels in the pixel buffer will be subjected
  106.  * to texturing, scissoring, stippling, alpha testing, stenciling,
  107.  * depth testing, blending, and finally written to the frame buffer.
  108.  */
  109. void gl_flush_pb( GLcontext *ctx )
  110. {
  111.    struct pixel_buffer* PB = ctx->PB;
  112.  
  113.    GLubyte mask[PB_SIZE];
  114.    GLubyte saved[PB_SIZE][4];
  115.  
  116.    if (PB->count==0)  goto CleanUp;
  117.  
  118.    /* initialize mask array and clip pixels simultaneously */
  119.    {
  120.       GLint xmin = ctx->Buffer->Xmin;
  121.       GLint xmax = ctx->Buffer->Xmax;
  122.       GLint ymin = ctx->Buffer->Ymin;
  123.       GLint ymax = ctx->Buffer->Ymax;
  124.       GLint *x = PB->x;
  125.       GLint *y = PB->y;
  126.       GLuint i, n = PB->count;
  127.       for (i=0;i<n;i++) {
  128.          mask[i] = (x[i]>=xmin) & (x[i]<=xmax) & (y[i]>=ymin) & (y[i]<=ymax);
  129.       }
  130.    }
  131.  
  132.    if (ctx->Visual->RGBAflag) {
  133.       /* RGBA COLOR PIXELS */
  134.       if (PB->mono && ctx->MutablePixels) {
  135.      /* Copy flat color to all pixels */
  136.          GLuint i;
  137.          for (i=0; i<PB->count; i++) {
  138.             PB->rgba[i][RCOMP] = PB->color[RCOMP];
  139.             PB->rgba[i][GCOMP] = PB->color[GCOMP];
  140.             PB->rgba[i][BCOMP] = PB->color[BCOMP];
  141.             PB->rgba[i][ACOMP] = PB->color[ACOMP];
  142.          }
  143.       }
  144.  
  145.       /* If each pixel can be of a different color... */
  146.       if (ctx->MutablePixels || !PB->mono) {
  147.  
  148.      if (ctx->Texture.Enabled) {
  149.         gl_texture_pixels( ctx, 0,
  150.                                PB->count, PB->s, PB->t, PB->u, PB->lambda,
  151.                                PB->rgba);
  152.      }
  153.  
  154.      if (ctx->Fog.Enabled
  155.              && (ctx->Hint.Fog==GL_NICEST || PB->primitive==GL_BITMAP
  156.                  || ctx->Texture.Enabled)) {
  157.         gl_fog_rgba_pixels( ctx, PB->count, PB->z, PB->rgba );
  158.      }
  159.  
  160.          /* Scissoring already done above */
  161.  
  162.      if (ctx->Color.AlphaEnabled) {
  163.         if (gl_alpha_test( ctx, PB->count, PB->rgba, mask )==0) {
  164.            goto CleanUp;
  165.         }
  166.      }
  167.  
  168.      if (ctx->Stencil.Enabled) {
  169.         /* first stencil test */
  170.         if (gl_stencil_pixels( ctx, PB->count, PB->x, PB->y, mask )==0) {
  171.            goto CleanUp;
  172.         }
  173.         /* depth buffering w/ stencil */
  174.         gl_depth_stencil_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask );
  175.      }
  176.      else if (ctx->Depth.Test) {
  177.         /* regular depth testing */
  178.         (*ctx->Driver.DepthTestPixels)( ctx, PB->count, PB->x, PB->y, PB->z, mask );
  179.      }
  180.  
  181.          if (ctx->RasterMask & NO_DRAW_BIT) {
  182.             goto CleanUp;
  183.          }
  184.  
  185.          if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  186.             /* make a copy of the colors */
  187.             MEMCPY( saved, PB->rgba, PB->count * 4 * sizeof(GLubyte) );
  188.          }
  189.  
  190.          if (ctx->Color.SWLogicOpEnabled) {
  191.             gl_logicop_rgba_pixels( ctx, PB->count, PB->x, PB->y,
  192.                                     PB->rgba, mask);
  193.          }
  194.          else if (ctx->Color.BlendEnabled) {
  195.             gl_blend_pixels( ctx, PB->count, PB->x, PB->y, PB->rgba, mask);
  196.          }
  197.  
  198.          if (ctx->Color.SWmasking) {
  199.             gl_mask_rgba_pixels(ctx, PB->count, PB->x, PB->y, PB->rgba, mask);
  200.          }
  201.  
  202.          /* write pixels */
  203.          (*ctx->Driver.WriteRGBAPixels)( ctx, PB->count, PB->x, PB->y,
  204.                                          PB->rgba, mask );
  205.          if (ctx->RasterMask & ALPHABUF_BIT) {
  206.             gl_write_alpha_pixels( ctx, PB->count, PB->x, PB->y, PB->rgba, mask );
  207.          }
  208.  
  209.          if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  210.             /*** Also draw to back buffer ***/
  211.             (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  212.             if (ctx->Color.SWLogicOpEnabled) {
  213.                gl_logicop_rgba_pixels( ctx, PB->count, PB->x, PB->y,
  214.                                        PB->rgba, mask);
  215.             }
  216.             else if (ctx->Color.BlendEnabled) {
  217.                gl_blend_pixels( ctx, PB->count, PB->x, PB->y, saved, mask );
  218.             }
  219.             if (ctx->Color.SWmasking) {
  220.                gl_mask_rgba_pixels(ctx, PB->count, PB->x, PB->y, saved, mask);
  221.             }
  222.             (*ctx->Driver.WriteRGBAPixels)( ctx, PB->count, PB->x, PB->y,
  223.                                             saved, mask);
  224.             if (ctx->RasterMask & ALPHABUF_BIT) {
  225.                ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
  226.                gl_write_alpha_pixels( ctx, PB->count, PB->x, PB->y,
  227.                                       saved, mask );
  228.                ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
  229.             }
  230.             (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  231.             /*** ALL DONE ***/
  232.          }
  233.       }
  234.       else {
  235.      /* Same color for all pixels */
  236.  
  237.          /* Scissoring already done above */
  238.  
  239.      if (ctx->Color.AlphaEnabled) {
  240.         if (gl_alpha_test( ctx, PB->count, PB->rgba, mask )==0) {
  241.            goto CleanUp;
  242.         }
  243.      }
  244.  
  245.      if (ctx->Stencil.Enabled) {
  246.         /* first stencil test */
  247.         if (gl_stencil_pixels( ctx, PB->count, PB->x, PB->y, mask )==0) {
  248.            goto CleanUp;
  249.         }
  250.         /* depth buffering w/ stencil */
  251.         gl_depth_stencil_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask );
  252.      }
  253.      else if (ctx->Depth.Test) {
  254.         /* regular depth testing */
  255.         (*ctx->Driver.DepthTestPixels)( ctx, PB->count, PB->x, PB->y, PB->z, mask );
  256.      }
  257.  
  258.          if (ctx->RasterMask & NO_DRAW_BIT) {
  259.             goto CleanUp;
  260.          }
  261.  
  262.          /* write pixels */
  263.          {
  264.             GLubyte red, green, blue, alpha;
  265.             red   = PB->color[RCOMP];
  266.             green = PB->color[GCOMP];
  267.             blue  = PB->color[BCOMP];
  268.             alpha = PB->color[ACOMP];
  269.         (*ctx->Driver.Color)( ctx, red, green, blue, alpha );
  270.          }
  271.          (*ctx->Driver.WriteMonoRGBAPixels)( ctx, PB->count, PB->x, PB->y, mask );
  272.          if (ctx->RasterMask & ALPHABUF_BIT) {
  273.             gl_write_mono_alpha_pixels( ctx, PB->count, PB->x, PB->y,
  274.                                         PB->color[ACOMP], mask );
  275.          }
  276.  
  277.          if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  278.             /*** Also render to back buffer ***/
  279.             (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  280.             (*ctx->Driver.WriteMonoRGBAPixels)( ctx, PB->count, PB->x, PB->y, mask );
  281.             if (ctx->RasterMask & ALPHABUF_BIT) {
  282.                ctx->Buffer->Alpha = ctx->Buffer->BackAlpha;
  283.                gl_write_mono_alpha_pixels( ctx, PB->count, PB->x, PB->y,
  284.                                            PB->color[ACOMP], mask );
  285.                ctx->Buffer->Alpha = ctx->Buffer->FrontAlpha;
  286.             }
  287.             (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  288.      }
  289.          /*** ALL DONE ***/
  290.       }
  291.    }
  292.    else {
  293.       /* COLOR INDEX PIXELS */
  294.  
  295.       /* If we may be writting pixels with different indexes... */
  296.       if (PB->mono && ctx->MutablePixels) {
  297.      /* copy index to all pixels */
  298.          GLuint n = PB->count, indx = PB->index;
  299.          GLuint *pbindex = PB->i;
  300.          do {
  301.         *pbindex++ = indx;
  302.             n--;
  303.      } while (n);
  304.       }
  305.  
  306.       if (ctx->MutablePixels || !PB->mono) {
  307.      /* Pixel color index may be modified */
  308.          GLuint *isave = (GLuint*)saved;
  309.  
  310.      if (ctx->Fog.Enabled
  311.              && (ctx->Hint.Fog==GL_NICEST || PB->primitive==GL_BITMAP)) {
  312.         gl_fog_ci_pixels( ctx, PB->count, PB->z, PB->i );
  313.      }
  314.  
  315.          /* Scissoring already done above */
  316.  
  317.      if (ctx->Stencil.Enabled) {
  318.         /* first stencil test */
  319.         if (gl_stencil_pixels( ctx, PB->count, PB->x, PB->y, mask )==0) {
  320.            goto CleanUp;
  321.         }
  322.         /* depth buffering w/ stencil */
  323.         gl_depth_stencil_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask );
  324.      }
  325.      else if (ctx->Depth.Test) {
  326.         /* regular depth testing */
  327.         (*ctx->Driver.DepthTestPixels)( ctx, PB->count, PB->x, PB->y, PB->z, mask );
  328.      }
  329.  
  330.          if (ctx->RasterMask & NO_DRAW_BIT) {
  331.             goto CleanUp;
  332.          }
  333.  
  334.          if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  335.             /* make a copy of the indexes */
  336.             MEMCPY( isave, PB->i, PB->count * sizeof(GLuint) );
  337.          }
  338.  
  339.          if (ctx->Color.SWLogicOpEnabled) {
  340.             gl_logicop_ci_pixels( ctx, PB->count, PB->x, PB->y, PB->i, mask );
  341.          }
  342.  
  343.          if (ctx->Color.SWmasking) {
  344.             gl_mask_index_pixels( ctx, PB->count, PB->x, PB->y, PB->i, mask );
  345.          }
  346.  
  347.          /* write pixels */
  348.          (*ctx->Driver.WriteCI32Pixels)( ctx, PB->count, PB->x, PB->y,
  349.                                           PB->i, mask );
  350.  
  351.          if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  352.             /*** Also write to back buffer ***/
  353.             (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  354.             MEMCPY( PB->i, isave, PB->count * sizeof(GLuint) );
  355.             if (ctx->Color.SWLogicOpEnabled) {
  356.                gl_logicop_ci_pixels( ctx, PB->count, PB->x, PB->y, PB->i, mask );
  357.             }
  358.             if (ctx->Color.SWmasking) {
  359.                gl_mask_index_pixels( ctx, PB->count, PB->x, PB->y,
  360.                                      PB->i, mask );
  361.             }
  362.             (*ctx->Driver.WriteCI32Pixels)( ctx, PB->count, PB->x, PB->y,
  363.                                              PB->i, mask );
  364.             (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  365.          }
  366.  
  367.          /*** ALL DONE ***/
  368.       }
  369.       else {
  370.      /* Same color index for all pixels */
  371.  
  372.          /* Scissoring already done above */
  373.  
  374.      if (ctx->Stencil.Enabled) {
  375.         /* first stencil test */
  376.         if (gl_stencil_pixels( ctx, PB->count, PB->x, PB->y, mask )==0) {
  377.            goto CleanUp;
  378.         }
  379.         /* depth buffering w/ stencil */
  380.         gl_depth_stencil_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask );
  381.      }
  382.      else if (ctx->Depth.Test) {
  383.         /* regular depth testing */
  384.         (*ctx->Driver.DepthTestPixels)( ctx, PB->count, PB->x, PB->y, PB->z, mask );
  385.      }
  386.          
  387.          if (ctx->RasterMask & NO_DRAW_BIT) {
  388.             goto CleanUp;
  389.          }
  390.  
  391.          /* write pixels */
  392.          (*ctx->Driver.Index)( ctx, PB->index );
  393.          (*ctx->Driver.WriteMonoCIPixels)( ctx, PB->count, PB->x, PB->y, mask );
  394.  
  395.          if (ctx->RasterMask & FRONT_AND_BACK_BIT) {
  396.             /*** Also write to back buffer ***/
  397.             (*ctx->Driver.SetBuffer)( ctx, GL_BACK );
  398.             (*ctx->Driver.WriteMonoCIPixels)( ctx, PB->count, PB->x, PB->y, mask );
  399.             (*ctx->Driver.SetBuffer)( ctx, GL_FRONT );
  400.          }
  401.          /*** ALL DONE ***/
  402.       }
  403.    }
  404.  
  405. CleanUp:
  406.    PB->count = 0;
  407. }
  408.  
  409.  
  410.